package mahmoud.sigir.search;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;


import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import mahmoud.utils.Result;
import mahmoud.utils.MinHeap;
import mahmoud.utils.WieghtedTerm;
import mahmoud.utils.PorterStemAnalyzer;

public abstract class Searcher 
{
	public Analyzer analyzer = null;
	public IndexReader luceneReader = null;
	public IndexSearcher luceneSearcher = null;
	public QueryParser _parser = null;
	protected String IndexLocation;
	protected boolean searcherOpenFlag = false;
	public static final int TopK_DOCs = 20;
	protected String Field = "All";
	protected static final String OhsumedIndexLocation = "resources/builtIndexes/OHSUMED/";
	protected static final String TrecFTIndexLocation = "resources/builtIndexes/TREC-FT/";
	
	public Searcher(String Location)
	{
		analyzer = new PorterStemAnalyzer();
		_parser = new QueryParser(Version.LUCENE_30,"body", analyzer);
		IndexLocation = Location;
	}
	public  boolean openSearcher()
	{
		try 
		{
			luceneReader = IndexReader.open(FSDirectory.open(new File(IndexLocation)));
			luceneSearcher = new IndexSearcher(luceneReader);
		} catch (IOException e) 
		{
			e.printStackTrace();
			return searcherOpenFlag;
		}
		searcherOpenFlag = true;
		return searcherOpenFlag;
	}
	public boolean closeSearcher()
	{
		try 
		{
			luceneReader.close();
			luceneSearcher.close();
		} catch (IOException e) 
		{
			e.printStackTrace();
			return !searcherOpenFlag;
		}
		searcherOpenFlag = false;
		return !searcherOpenFlag;
	}
	public boolean checkOpenStatus()
	{
		return searcherOpenFlag;
	}
	protected MinHeap<Result> constructResults(TopDocs TD)
	{
		if(!searcherOpenFlag)
		{
			System.out.println("You need to open searcher then close to be able to do this operation");
			return null;
		}
		if(TD == null)
		{
			return null;
		}
		MinHeap<Result> ResultsHeap = new MinHeap<Result>(TopK_DOCs);
		for(int i =0 ; i< Searcher.TopK_DOCs ; i++)
		{
//			if(i==10)break;
			Document result;
			try 
			{
//				result = luceneSearcher.doc(TD.scoreDocs[i].doc);
				
				result =luceneReader.document(TD.scoreDocs[i].doc);
//				System.out.println(TD.totalHits + " " +result.getField("Title"));
				int id = TD.scoreDocs[i].doc;
				String docID = result.getField("docID").stringValue();
				String title = result.getField("Title").stringValue();
				String filePath = result.getField("Path").stringValue();
				String content = result.getField("All").stringValue();
//				System.out.println((i+1)+ ". "+TD.totalHits + "\t"+  TD.scoreDocs[i].score+" "+content  +" "+ filePath );

				ResultsHeap.add(new Result(id,docID,title, filePath,content,TD.scoreDocs[i].score));
			}
			catch (IOException e) 
			{
//				e.printStackTrace();
				System.out.println("something is happenning here..!"+TD.totalHits + " "+ this.searcherOpenFlag);
				System.exit(0);
			}
		}
		return ResultsHeap;
	}
	protected Query constructQuery(ArrayList<WieghtedTerm> Q)
	{
		if(!checkOpenStatus())
		{
			System.out.println("You need to open searcher then close to be able to do this operation");
			return null;
		}
		BooleanQuery totalQ=new BooleanQuery() ;
		BooleanQuery.setMaxClauseCount(Q.size());
		try 
		{
			QueryParser parser = new QueryParser(Version.LUCENE_30,"All",analyzer);
			parser.setDefaultOperator(QueryParser.Operator.OR);
			BooleanQuery.setMaxClauseCount(Q.size());
			Query termQ;
			
			for(WieghtedTerm wt : Q)
			{
				termQ = parser.parse(wt.Term);
				termQ.setBoost((float) wt.wieght);
				totalQ.add(termQ,BooleanClause.Occur.SHOULD);
			}
		} 
		catch (Exception ie) 
		{
			ie.printStackTrace();
		}
		return totalQ;
	}
	public abstract  MinHeap<Result> luceneSearch(ArrayList<WieghtedTerm> Q);

	public static void main(String[] argc)
	{
		System.out.println("from searcher");
//		Searcher s = new Searcher(new Indexer(new TrecParser("D:\\dDocuments\\Code\\TREC4\\FT"), "D:\\dDocuments\\Code\\builtIndexes\\TREC-FT\\"));
//		s.constructQuery(Q);
		
	}


}
